﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Diagnostics;

namespace TubeTest
{
    class TubeNode
    {
        public const int DisplacementSamples = 32;

        public Vector3 Position;
        public float radius = 1.0f;
        public float[] displacement = new float[DisplacementSamples];

        public VertexPositionNormalTexture[] Vertices = new VertexPositionNormalTexture[DisplacementSamples];
        public Vector3 Direction = Vector3.Zero;
        public Vector3 Up = Vector3.Zero;
        public Vector3 Right = Vector3.Zero;
        public Vector3 Backwards = Vector3.Zero;

        public float texDistance = 0.0f;
        public float texStretch = 0.05f;

        static Random rnd = new Random();

        public TubeNode()
        {
            Position = Vector3.Zero;
            clearDisplacement();
        }

        public TubeNode(Vector3 pPosition)
        {
            Position = pPosition;
            clearDisplacement();
        }

        public TubeNode(float X, float Y, float Z)
        {
            Position.X = X;
            Position.Y = Y;
            Position.Z = Z;
        }

        public static Vector3 upward(Vector3 v)
        {
            return new Vector3(-v.Y, v.X, -v.Z);
        }

        public void orient(TubeNode prev, TubeNode next)
        {
            Vector3 D = Vector3.Zero;

            if (prev == null && next == null) return;

            if (prev != null && next == null)
            {
                D = prev.Position - Position;
                texDistance = prev.texDistance + (Position - prev.Position).Length();
                //Trace.WriteLine("Type 1");
            }
            
            if (next != null && prev == null)
            {
                D = Position - next.Position;
                texDistance = 0.0f;
                //Trace.WriteLine("Type 2");
            }

            if (next != null && prev != null)
            {
                D = (prev.Position - next.Position) * 0.5f;
                //D = prev.Position - Position;
                texDistance = prev.texDistance + (Position - prev.Position).Length();
                //Trace.WriteLine("Type 0");
            }

            Vector3 U = upward(D);
            U.Normalize();
            Right = Vector3.Cross(U, D);
            Vector3.Normalize(ref Right, out Right);
            Backwards = Vector3.Cross(Right, U);
            Vector3.Normalize(ref Backwards, out Backwards);
            Up = Vector3.Cross(Backwards, Right);
        }

        public void updateVertices(bool inverted)
        {
            for (int i = 0; i < DisplacementSamples; ++i)
            {
                float perc = (float)i / (float)DisplacementSamples;
                float angle = MathHelper.TwoPi * perc;
                float magnitude = radius * (1.0f + displacement[i]);

                Vertices[i].Position = Position 
                    + (float)Math.Cos(angle) * Right * magnitude 
                    + (float)Math.Sin(angle) * Up * magnitude;

                Vertices[i].Normal = (Vertices[i].Position - Position);
                Vertices[i].Normal.Normalize();

                if (inverted) Vertices[i].Normal = -Vertices[i].Normal;

                Vertices[i].TextureCoordinate.X = perc;
                Vertices[i].TextureCoordinate.Y = texDistance * texStretch;
            }
        }

        public void displacementNoise(float magnitude)
        {
            
            for (int i = 0; i < DisplacementSamples; ++i)
            {
                displacement[i] = (float)(rnd.NextDouble() * magnitude);
            }
        }
            
        public void clearDisplacement()
        {
            for (int i = 0; i < DisplacementSamples; ++i)
                displacement[i] = 0.0f;
        }
    }
}
